/*
 * filename	:Flash_Port.h
 * This file is spi driver for w25Q16
 *
 * Change Logs:
 * Date		Author		Notes
 * 2018.0403	guanjingxin	the first version
 *
 */

#ifndef _FLASH_PORT_H
#define _FLASH_PORT_H



#include "BasicTypeDef.h"        /* common data types def files used in our work group member                  */
#include "gd32f30x.h"

#define  SPI_FLASH_CS_LOW()            gpio_bit_reset(GPIOB, GPIO_PIN_6)
#define  SPI_FLASH_CS_HIGH()           gpio_bit_set(GPIOB, GPIO_PIN_6)
/*
************************************************************************************************************************************
*                          config Flash_Port.h/c  OS environment
************************************************************************************************************************************
*/

#define      USE_THIS_SPI_FLASH_PORT_WITH_OS           1 /* 0:no OS; 1: in OS environment(default uCOSII)             */
#define      USE_READ_WITH_STM32F2XX_DMA               1 /* 0:do not use DMA read,(normal speed) 1:use DMA(highspeed) */
/* -------------------------------------------------------------------------------------------------------------- 
                                        READ SPEED TEST(with CPU SPI BUS speed < 25MHZ,this stm32f107 at 19.5Mhz)
                                 ==============================
N0  DMA                                    03 cmd               0b cmd

10000 circle read 4byte                   201ms                217ms
10000 circle read 1024byte                24098ms              23820ms
YES DMA                                   
10000 circle read 4byte                   217ms                248ms
10000 circle read 1024byte                4747ms               4775ms
now we get the result:    use 03cmd NOT 0bcmd with DMA is the better way(what matter data size is small size,or mass size)
 -------------------------------------------------------------------------------------------------------------- */
/*
************************************************************************************************************************************
*                          include
************************************************************************************************************************************
*/

#if  USE_THIS_SPI_FLASH_PORT_WITH_OS
/* #include<includes.h>   */
#endif

#ifdef   SPIFLASH_GLOBALS
#define  SPIFLASH_EXT
#else
#define  SPIFLASH_EXT  extern
#endif                                  /* to declare global variables                                                */

/*  Block Address (BLOCK Erase unit(64KByte) for M25PXXX/SST25VFXXX/W25XXX )                                          */
#define FLASH_ADDR_BLOCK_0          0x000000   /* 0x000000~0x00FFFF 64Kbyte(ONE BLOCK)                                */
#define FLASH_ADDR_BLOCK_1          0x010000   /* 0x010000~0x01FFFF 128Kbyte                                          */
#define FLASH_ADDR_BLOCK_2          0x020000   /* 0x020000~0x02FFFF                                                   */
#define FLASH_ADDR_BLOCK_3          0x030000   /* 0x030000~0x03FFFF                                                   */
#define FLASH_ADDR_BLOCK_4          0x040000   /* 0x040000~0x04FFFF                                                   */
#define FLASH_ADDR_BLOCK_5          0x050000   /* 0x050000~0x05FFFF                                                   */
#define FLASH_ADDR_BLOCK_6          0x060000   /* 0x060000~0x06FFFF                                                   */
#define FLASH_ADDR_BLOCK_7          0x070000   /* 0x070000~0x07FFFF                                                   */
#define FLASH_ADDR_BLOCK_8          0x080000   /* 0x080000~0x08FFFF                                                   */
#define FLASH_ADDR_BLOCK_9          0x090000   /* 0x090000~0x09FFFF                                                   */
#define FLASH_ADDR_BLOCK_10         0x0A0000   /* 0x0A0000~0x0AFFFF                                                   */ 
#define FLASH_ADDR_BLOCK_11         0x0B0000   /* 0x0B0000~0x0BFFFF                                                   */
#define FLASH_ADDR_BLOCK_12         0x0C0000   /* 0x0C0000~0x0CFFFF                                                   */
#define FLASH_ADDR_BLOCK_13         0x0D0000   /* 0x0D0000~0x0DFFFF                                                   */
#define FLASH_ADDR_BLOCK_14         0x0E0000   /* 0x0E0000~0x0EFFFF                                                   */
#define FLASH_ADDR_BLOCK_15         0x0F0000   /* 0x0F0000~0x0FFFFF 1Mbyte                                            */
#define FLASH_ADDR_BLOCK_16         0x100000   /* 0x100000~0x10FFFF                                                   */
#define FLASH_ADDR_BLOCK_17         0x110000   /* 0x110000~0x11FFFF                                                   */
#define FLASH_ADDR_BLOCK_18         0x120000   /* 0x120000~0x12FFFF                                                   */
#define FLASH_ADDR_BLOCK_19         0x130000   /* 0x130000~0x13FFFF                                                   */
#define FLASH_ADDR_BLOCK_20         0x140000   /* 0x140000~0x14FFFF                                                   */
#define FLASH_ADDR_BLOCK_21         0x150000   /* 0x150000~0x15FFFF                                                   */
#define FLASH_ADDR_BLOCK_22         0x160000   /* 0x160000~0x16FFFF                                                   */
#define FLASH_ADDR_BLOCK_23         0x170000   /* 0x170000~0x17FFFF                                                   */
#define FLASH_ADDR_BLOCK_24         0x180000   /* 0x180000~0x18FFFF                                                   */
#define FLASH_ADDR_BLOCK_25         0x190000   /* 0x190000~0x19FFFF                                                   */
#define FLASH_ADDR_BLOCK_26         0x1A0000   /* 0x1A0000~0x1AFFFF                                                   */
#define FLASH_ADDR_BLOCK_27         0x1B0000   /* 0x1B0000~0x1BFFFF                                                   */
#define FLASH_ADDR_BLOCK_28         0x1C0000   /* 0x1C0000~0x1CFFFF                                                   */
#define FLASH_ADDR_BLOCK_29         0x1D0000   /* 0x1D0000~0x1DFFFF                                                   */
#define FLASH_ADDR_BLOCK_30         0x1E0000   /* 0x1E0000~0x1EFFFF                                                   */
#define FLASH_ADDR_BLOCK_31         0x1F0000   /* 0x1F0000~0x1FFFFF 2Mbyte                                            */
#define FLASH_ADDR_BLOCK_32         0x200000   /* 0x200000~0x20FFFF                                                   */
#define FLASH_ADDR_BLOCK_33         0x210000   /* 0x210000~0x21FFFF                                                   */
#define FLASH_ADDR_BLOCK_34         0x220000   /* 0x220000~0x22FFFF                                                   */
#define FLASH_ADDR_BLOCK_35         0x230000   /* 0x230000~0x23FFFF                                                   */
#define FLASH_ADDR_BLOCK_36         0x240000   /* 0x240000~0x24FFFF                                                   */
#define FLASH_ADDR_BLOCK_37         0x250000   /* 0x250000~0x25FFFF                                                   */
#define FLASH_ADDR_BLOCK_38         0x260000   /* 0x260000~0x26FFFF                                                   */
#define FLASH_ADDR_BLOCK_39         0x270000   /* 0x270000~0x27FFFF                                                   */
#define FLASH_ADDR_BLOCK_40         0x280000   /* 0x280000~0x28FFFF                                                   */ 
#define FLASH_ADDR_BLOCK_41         0x290000   /* 0x290000~0x29FFFF                                                   */
#define FLASH_ADDR_BLOCK_42         0x2A0000   /* 0x2A0000~0x2AFFFF                                                   */
#define FLASH_ADDR_BLOCK_43         0x2B0000   /* 0x2B0000~0x2BFFFF                                                   */
#define FLASH_ADDR_BLOCK_44         0x2C0000   /* 0x2C0000~0x2CFFFF                                                   */
#define FLASH_ADDR_BLOCK_45         0x2D0000   /* 0x2D0000~0x2DFFFF                                                   */
#define FLASH_ADDR_BLOCK_46         0x2E0000   /* 0x2E0000~0x2EFFFF                                                   */
#define FLASH_ADDR_BLOCK_47         0x2F0000   /* 0x2F0000~0x2FFFFF 3Mbyte                                            */
#define FLASH_ADDR_BLOCK_48         0x300000   /* 0x300000~0x30FFFF                                                   */
#define FLASH_ADDR_BLOCK_49         0x310000   /* 0x310000~0x31FFFF                                                   */
#define FLASH_ADDR_BLOCK_50         0x320000   /* 0x320000~0x32FFFF                                                   */
#define FLASH_ADDR_BLOCK_51         0x330000   /* 0x330000~0x33FFFF                                                   */
#define FLASH_ADDR_BLOCK_52         0x340000   /* 0x340000~0x34FFFF                                                   */
#define FLASH_ADDR_BLOCK_53         0x350000   /* 0x350000~0x35FFFF                                                   */
#define FLASH_ADDR_BLOCK_54         0x360000   /* 0x360000~0x36FFFF                                                   */
#define FLASH_ADDR_BLOCK_55         0x370000   /* 0x370000~0x37FFFF                                                   */
#define FLASH_ADDR_BLOCK_56         0x380000   /* 0x380000~0x38FFFF                                                   */
#define FLASH_ADDR_BLOCK_57         0x390000   /* 0x390000~0x39FFFF                                                   */
#define FLASH_ADDR_BLOCK_58         0x3A0000   /* 0x3A0000~0x3AFFFF                                                   */
#define FLASH_ADDR_BLOCK_59         0x3B0000   /* 0x3B0000~0x3BFFFF                                                   */
#define FLASH_ADDR_BLOCK_60         0x3C0000   /* 0x3C0000~0x3CFFFF                                                   */
#define FLASH_ADDR_BLOCK_61         0x3D0000   /* 0x3D0000~0x3DFFFF                                                   */
#define FLASH_ADDR_BLOCK_62         0x3E0000   /* 0x3E0000~0x3EFFFF                                                   */
#define FLASH_ADDR_BLOCK_63         0x3F0000   /* 0x3F0000~0x3FFFFF 4Mbyte                                            */

/* chips supported                                                                                                    */
#define FLASH_JEDEC_ID_SST25VF020B  0xBF258C   /* Identify:SST,serial flash,SST25VF020B,0.25Mbyte                     */
#define FLASH_JEDEC_ID_SST25VF040B  0xBF258D   /* Identify:SST,serial flash,SST25VF040B,0.5Mbyte                      */
#define FLASH_JEDEC_ID_SST25VF080B  0xBF258E   /* Identify:SST,serial flash,SST25VF080B,1Mbyte                        */
#define FLASH_JEDEC_ID_SST25VF016B  0xBF2541   /* Identify:SST,serial flash,SST25VF016B,2Mbyte                        */ 
#define FLASH_JEDEC_ID_SST25VF032B  0xBF254A   /* Identify:SST,serial flash,SST25VF032B,4Mbyte                        */
#define JEDEC_MANUFACTURER_SST      0xBF   /* Identify:SST                                                            */
#define JEDEC_MANUFACTURER_WINBOND  0xEF   /* Identify:winbond                                                        */

                             
/* command of the serial flash                                                                                        */
                                   
#define FLASH_CMD_WREN             0x06  /* Write Enable;                 SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_WRDI             0x04  /* Write Disable;                SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_RDSR             0x05  /* Read status register;         SST25VFxxx/M25Pxxx/W25xxx use the same code */                        
#define FLASH_CMD_WRSR             0x01  /* Write status register;        SST25VFxxx/M25Pxxx/W25xxx use the same code */  
#define FLASH_CMD_READ             0x03  /* Read data byte(s);     <25MHz SST25VFxxx/M25Pxxx/W25xxx use the same code */       
#define FLASH_CMD_FAST_READ        0x0B  /* Fast Read data byte(s);<50Mhz SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_SECTOR_ERASE     0x20  /* Erase one Sector(4Kbyte) data;SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_32KBLOCK_ERASE   0x52  /* Erase one Block(32Kbyte) data;SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_BLOCK_ERASE      0xD8  /* Erase one Block(64Kbyte) data;SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_CHIP_ERASE       0xC7  /* Erase whole Chip data;        SST25VFxxx/M25Pxxx/W25xxx use the same code */ 
#define FLASH_CMD_JEDEC_ID         0x9F  /* Read JEDEC_ID  code;          SST25VFxxx/M25Pxxx/W25xxx use the same code */
#define FLASH_CMD_PAGE_PROGRAM     0x02  /* Program One Data Byte(S/M/W same); PageProgram(<=256bytes)(Only M25/M25P) */
#define FLASH_CMD_AAIP             0xAD  /*Auto Address IncrementProgramming ,Only SST25VFXXX                         */
/* constant defne used in flash access                                                                                */
#define FLASH_DUMMY_BYTE           0xA5        /*SST25VFxxx/M25Pxxx/W25xxx use the same code                          */
#define FLASH_WIP_FLAG             0x01        /*!< Erase/Write In Progress (WIP) flag SST25VFxxx/M25Pxxx/W25xxx same */
#define FLASH_PAGESIZE            0x100        /* PageSize(<=256bytes)(Only M25/M25P/W25xxx)                          */

/*
************************************************************************************************************************************
*            application layer extern variables(CATION:usually used to CHECK whether the source is used )
************************************************************************************************************************************
*/

#if  USE_THIS_SPI_FLASH_PORT_WITH_OS
/* SPIFLASH_EXT OS_EVENT *  FlashAccess;                        /\*Source access the COM1 for multi-thread access safety               *\/  */
SPIFLASH_EXT T08U        FlashIsIdle;
#endif                                              

/* initialize SPI0 GPIO and parameter */
void spi_flash_init(void);
/* erase the specified flash sector */
void spi_flash_sector_erase(uint32_t sector_addr);
/* erase the entire flash */
void spi_flash_bulk_erase(void);
/* write more than one byte to the flash */
void spi_flash_page_write(uint8_t* pbuffer,uint32_t write_addr,uint16_t num_byte_to_write);
/* write block of data to the flash */
void spi_flash_buffer_write(uint8_t* pbuffer,uint32_t write_addr,uint16_t num_byte_to_write);
/* read a block of data from the flash */
void spi_flash_buffer_read(uint8_t* pbuffer,uint32_t read_addr,uint16_t num_byte_to_read);
/* read flash identification */
uint32_t spi_flash_read_id(void);
/* initiate a read data byte (read) sequence from the flash */
void spi_flash_start_read_sequence(uint32_t read_addr);
/* read a byte from the SPI flash */
uint8_t spi_flash_read_byte(void);
/* send a byte through the SPI interface and return the byte received from the SPI bus */
uint8_t spi_flash_send_byte(uint8_t byte);
/* send a half word through the SPI interface and return the half word received from the SPI bus */
uint16_t spi_flash_send_halfword(uint16_t half_word);
/* enable the write access to the flash */
void spi_flash_write_enable(void);
/* poll the status of the write in progress (wip) flag in the flash's status register */
void spi_flash_wait_for_write_end(void);

#endif
